package com.haohan.cloud.scm.common.tools.redis;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.haohan.cloud.scm.common.tools.constant.ToolsConstant;
import com.haohan.cloud.scm.common.tools.util.ScmIncrementUtil;
import com.pig4cloud.pigx.admin.api.entity.SysDictItem;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author dy
 * @date 2019/10/21
 */
@Slf4j
@Component
@AllArgsConstructor
public class RedisIdSnUpdateUtil {

    /**
     * 主键映射的 dict类型
     * type   id_sn_config
     * value:  实体类名称
     * label:  表名
     * description: 数据库名
     * remarks: 逻辑主键字段名
     */
    public static final String REDIS_SN_TYPE = "id_sn_config";
    private static final String QUERY_SN_SQL = "SELECT %s FROM %s WHERE tenant_id = %s ORDER BY id+0 DESC LIMIT 1";
    private static final String QUERY_ID_SQL = "SELECT %s FROM %s WHERE length(id)<10 ORDER BY id+0 DESC LIMIT 1";
    private static final Pattern PATTERN = Pattern.compile("\\d+");
    /**
     * 缓存值 增加值
     */
    private static final Integer ADD_NUM = 5;
    private final ScmIncrementUtil scmIncrementUtil;

    public void updateAllSn(List<SysDictItem> list, List<String> tenantIdList, JdbcTemplate jdbcTemplate) {
        for (SysDictItem item : list) {
            String column = item.getRemarks();
            String tableName = item.getLabel();
            String className = item.getValue();
            if (StrUtil.isBlank(column) || StrUtil.isBlank(tableName) || StrUtil.isBlank(className)) {
                continue;
            }
            tenantIdList.forEach(tenantId -> {
                // 数据库最大值
                String num = fetchSnNum(tableName, column, tenantId, jdbcTemplate);
                // 更新缓存 值加
                updateRedisNum(num, fetchSnKey(className, tenantId));
            });
        }
    }

    private String fetchSnKey(String className, String tenantId) {
        return ToolsConstant.SN_PREFIX.concat(className).concat(":").concat(tenantId);
    }

    private String fetchSnNum(String tableName, String columnName, String tenantId, JdbcTemplate jdbcTemplate) {
        try {
            String sql = String.format(QUERY_SN_SQL, columnName, tableName, tenantId);
            List<Map<String, Object>> list = jdbcTemplate.queryForList(sql);
            // 结果集第一条, 无记录时返回0
            if (CollUtil.isEmpty(list)) {
                return "0";
            }
            String sn = list.get(0).get(columnName).toString();
            // 逻辑主键处理
            Matcher matcher = PATTERN.matcher(sn);
            if (matcher.find()) {
                String num = matcher.group();
                num = num.substring(tenantId.length());
                return num;
            }
        } catch (Exception e) {
            log.debug("fetchSnNum==error==");
            log.debug(e.getMessage());
        }
        return null;
    }

    /**
     * 获取 表 逻辑主键的数字段
     *
     * @param tableName
     * @param jdbcTemplate
     * @return
     */
    private String fetchIdNum(String tableName, JdbcTemplate jdbcTemplate) {
        try {
            String column = "id";
            String sql = String.format(QUERY_ID_SQL, column, tableName);
            List<Map<String, Object>> result = jdbcTemplate.queryForList(sql);
            // 结果集第一条, 无记录时返回0
            if (CollUtil.isEmpty(result)) {
                return "0";
            }
            return result.get(0).get(column).toString();
        } catch (Exception e) {
            log.debug("fetchIdNum==error==");
            log.debug(e.getMessage());
        }
        return null;
    }


    /**
     * 更新 缓存中 物理主键id 的数值
     *
     * @param list
     * @param jdbcTemplate
     */
    public void updateAllId(List<SysDictItem> list, JdbcTemplate jdbcTemplate) {
        list.forEach(item -> {
            String tableName = item.getLabel();
            String className = item.getValue();
            if (StrUtil.isNotBlank(className) && StrUtil.isNotBlank(tableName)) {
                // 数据库最大值
                String num = fetchIdNum(tableName, jdbcTemplate);
                String idKey = ToolsConstant.ID_PREFIX.concat(className);
                // 更新缓存 值加
                updateRedisNum(num, idKey);
            }
        });
    }

    /**
     * 更新缓存 在数据库查询值上增加
     *
     * @param num
     * @param key
     */
    private void updateRedisNum(String num, String key) {
        try {
            if (StrUtil.isNotEmpty(num)) {
                int number = Integer.parseInt(num) + ADD_NUM;
                scmIncrementUtil.setValue(key, Integer.toString(number), 0);
            }
        } catch (Exception e) {
            log.debug("updateRedisNum==error==");
            log.debug(e.getMessage());
        }
    }

}
